﻿using System;
using UnityEngine;

namespace RootMotion.FinalIK
{
	// Token: 0x02000034 RID: 52
	[Serializable]
	public class IKEffector
	{
		// Token: 0x06000268 RID: 616 RVA: 0x0002487C File Offset: 0x00022A7C
		public IKEffector()
		{
		}

		// Token: 0x06000269 RID: 617 RVA: 0x00024924 File Offset: 0x00022B24
		public IKEffector(Transform bone, Transform[] childBones)
		{
			this.bone = bone;
			this.childBones = childBones;
		}

		// Token: 0x0600026A RID: 618 RVA: 0x000039CE File Offset: 0x00001BCE
		public IKSolver.Node GetNode(IKSolverFullBody solver)
		{
			return solver.chain[this.chainIndex].nodes[this.nodeIndex];
		}

		// Token: 0x17000027 RID: 39
		// (get) Token: 0x0600026B RID: 619 RVA: 0x000039E9 File Offset: 0x00001BE9
		// (set) Token: 0x0600026C RID: 620 RVA: 0x000039F1 File Offset: 0x00001BF1
		public bool isEndEffector { get; set; }

		// Token: 0x0600026D RID: 621 RVA: 0x000249DC File Offset: 0x00022BDC
		public void PinToBone(float positionWeight, float rotationWeight)
		{
			this.position = this.bone.position;
			this.positionWeight = Mathf.Clamp(positionWeight, 0f, 1f);
			this.rotation = this.bone.rotation;
			this.rotationWeight = Mathf.Clamp(rotationWeight, 0f, 1f);
		}

		// Token: 0x0600026E RID: 622 RVA: 0x00024A38 File Offset: 0x00022C38
		public bool IsValid(IKSolver solver, ref string message)
		{
			if (this.bone == null)
			{
				message = "IK Effector bone is null.";
				return false;
			}
			if (solver.GetPoint(this.bone) == null)
			{
				message = "IK Effector is referencing to a bone '" + this.bone.name + "' that does not excist in the Node Chain.";
				return false;
			}
			foreach (Transform x in this.childBones)
			{
				if (x == null)
				{
					message = "IK Effector contains a null reference.";
					return false;
				}
			}
			foreach (Transform transform in this.childBones)
			{
				if (solver.GetPoint(transform) == null)
				{
					message = "IK Effector is referencing to a bone '" + transform.name + "' that does not excist in the Node Chain.";
					return false;
				}
			}
			if (this.planeBone1 != null && solver.GetPoint(this.planeBone1) == null)
			{
				message = "IK Effector is referencing to a bone '" + this.planeBone1.name + "' that does not excist in the Node Chain.";
				return false;
			}
			if (this.planeBone2 != null && solver.GetPoint(this.planeBone2) == null)
			{
				message = "IK Effector is referencing to a bone '" + this.planeBone2.name + "' that does not excist in the Node Chain.";
				return false;
			}
			if (this.planeBone3 != null && solver.GetPoint(this.planeBone3) == null)
			{
				message = "IK Effector is referencing to a bone '" + this.planeBone3.name + "' that does not excist in the Node Chain.";
				return false;
			}
			return true;
		}

		// Token: 0x0600026F RID: 623 RVA: 0x00024BD0 File Offset: 0x00022DD0
		public void Initiate(IKSolverFullBody solver)
		{
			this.position = this.bone.position;
			this.rotation = this.bone.rotation;
			this.animatedPlaneRotation = Quaternion.identity;
			solver.GetChainAndNodeIndexes(this.bone, out this.chainIndex, out this.nodeIndex);
			this.childChainIndexes = new int[this.childBones.Length];
			this.childNodeIndexes = new int[this.childBones.Length];
			for (int i = 0; i < this.childBones.Length; i++)
			{
				solver.GetChainAndNodeIndexes(this.childBones[i], out this.childChainIndexes[i], out this.childNodeIndexes[i]);
			}
			this.localPositions = new Vector3[this.childBones.Length];
			this.usePlaneNodes = false;
			if (this.planeBone1 != null)
			{
				solver.GetChainAndNodeIndexes(this.planeBone1, out this.plane1ChainIndex, out this.plane1NodeIndex);
				if (this.planeBone2 != null)
				{
					solver.GetChainAndNodeIndexes(this.planeBone2, out this.plane2ChainIndex, out this.plane2NodeIndex);
					if (this.planeBone3 != null)
					{
						solver.GetChainAndNodeIndexes(this.planeBone3, out this.plane3ChainIndex, out this.plane3NodeIndex);
						this.usePlaneNodes = true;
					}
				}
				this.isEndEffector = true;
			}
			else
			{
				this.isEndEffector = false;
			}
		}

		// Token: 0x06000270 RID: 624 RVA: 0x00024D38 File Offset: 0x00022F38
		public void ResetOffset(IKSolverFullBody solver)
		{
			solver.GetNode(this.chainIndex, this.nodeIndex).offset = Vector3.zero;
			for (int i = 0; i < this.childChainIndexes.Length; i++)
			{
				solver.GetNode(this.childChainIndexes[i], this.childNodeIndexes[i]).offset = Vector3.zero;
			}
		}

		// Token: 0x06000271 RID: 625 RVA: 0x000039FA File Offset: 0x00001BFA
		public void SetToTarget()
		{
			if (this.target == null)
			{
				return;
			}
			this.position = this.target.position;
			this.rotation = this.target.rotation;
		}

		// Token: 0x06000272 RID: 626 RVA: 0x00024D9C File Offset: 0x00022F9C
		public void OnPreSolve(IKSolverFullBody solver)
		{
			this.positionWeight = Mathf.Clamp(this.positionWeight, 0f, 1f);
			this.rotationWeight = Mathf.Clamp(this.rotationWeight, 0f, 1f);
			this.maintainRelativePositionWeight = Mathf.Clamp(this.maintainRelativePositionWeight, 0f, 1f);
			this.posW = this.positionWeight * solver.IKPositionWeight;
			this.rotW = this.rotationWeight * solver.IKPositionWeight;
			solver.GetNode(this.chainIndex, this.nodeIndex).effectorPositionWeight = this.posW;
			solver.GetNode(this.chainIndex, this.nodeIndex).effectorRotationWeight = this.rotW;
			solver.GetNode(this.chainIndex, this.nodeIndex).solverRotation = this.rotation;
			if (float.IsInfinity(this.positionOffset.x) || float.IsInfinity(this.positionOffset.y) || float.IsInfinity(this.positionOffset.z))
			{
				Debug.LogError("Invalid IKEffector.positionOffset (contains Infinity)! Please make sure not to set IKEffector.positionOffset to infinite values.", this.bone);
			}
			if (float.IsNaN(this.positionOffset.x) || float.IsNaN(this.positionOffset.y) || float.IsNaN(this.positionOffset.z))
			{
				Debug.LogError("Invalid IKEffector.positionOffset (contains NaN)! Please make sure not to set IKEffector.positionOffset to NaN values.", this.bone);
			}
			if (this.positionOffset.sqrMagnitude > 1E+10f)
			{
				Debug.LogError("Additive effector positionOffset detected in Full Body IK (extremely large value). Make sure you are not circularily adding to effector positionOffset each frame.", this.bone);
			}
			if (float.IsInfinity(this.position.x) || float.IsInfinity(this.position.y) || float.IsInfinity(this.position.z))
			{
				Debug.LogError("Invalid IKEffector.position (contains Infinity)!");
			}
			solver.GetNode(this.chainIndex, this.nodeIndex).offset += this.positionOffset * solver.IKPositionWeight;
			if (this.effectChildNodes && solver.iterations > 0)
			{
				for (int i = 0; i < this.childBones.Length; i++)
				{
					this.localPositions[i] = this.childBones[i].transform.position - this.bone.transform.position;
					solver.GetNode(this.childChainIndexes[i], this.childNodeIndexes[i]).offset += this.positionOffset * solver.IKPositionWeight;
				}
			}
			if (this.usePlaneNodes && this.maintainRelativePositionWeight > 0f)
			{
				this.animatedPlaneRotation = Quaternion.LookRotation(this.planeBone2.position - this.planeBone1.position, this.planeBone3.position - this.planeBone1.position);
			}
			this.firstUpdate = true;
		}

		// Token: 0x06000273 RID: 627 RVA: 0x00003A30 File Offset: 0x00001C30
		public void OnPostWrite()
		{
			this.positionOffset = Vector3.zero;
		}

		// Token: 0x06000274 RID: 628 RVA: 0x000250B8 File Offset: 0x000232B8
		public Quaternion GetPlaneRotation(IKSolverFullBody solver)
		{
			Vector3 solverPosition = solver.GetNode(this.plane1ChainIndex, this.plane1NodeIndex).solverPosition;
			Vector3 solverPosition2 = solver.GetNode(this.plane2ChainIndex, this.plane2NodeIndex).solverPosition;
			Vector3 solverPosition3 = solver.GetNode(this.plane3ChainIndex, this.plane3NodeIndex).solverPosition;
			Vector3 vector = solverPosition2 - solverPosition;
			Vector3 upwards = solverPosition3 - solverPosition;
			if (vector == Vector3.zero)
			{
				Warning.Log("Make sure you are not placing 2 or more FBBIK effectors of the same chain to exactly the same position.", this.bone, false);
				return Quaternion.identity;
			}
			return Quaternion.LookRotation(vector, upwards);
		}

		// Token: 0x06000275 RID: 629 RVA: 0x00025150 File Offset: 0x00023350
		public void Update(IKSolverFullBody solver)
		{
			if (this.firstUpdate)
			{
				this.animatedPosition = this.bone.position + solver.GetNode(this.chainIndex, this.nodeIndex).offset;
				this.firstUpdate = false;
			}
			solver.GetNode(this.chainIndex, this.nodeIndex).solverPosition = Vector3.Lerp(this.GetPosition(solver, out this.planeRotationOffset), this.position, this.posW);
			if (!this.effectChildNodes)
			{
				return;
			}
			for (int i = 0; i < this.childBones.Length; i++)
			{
				solver.GetNode(this.childChainIndexes[i], this.childNodeIndexes[i]).solverPosition = Vector3.Lerp(solver.GetNode(this.childChainIndexes[i], this.childNodeIndexes[i]).solverPosition, solver.GetNode(this.chainIndex, this.nodeIndex).solverPosition + this.localPositions[i], this.posW);
			}
		}

		// Token: 0x06000276 RID: 630 RVA: 0x00025264 File Offset: 0x00023464
		public Vector3 GetPosition(IKSolverFullBody solver, out Quaternion planeRotationOffset)
		{
			planeRotationOffset = Quaternion.identity;
			if (!this.isEndEffector)
			{
				return solver.GetNode(this.chainIndex, this.nodeIndex).solverPosition;
			}
			if (this.maintainRelativePositionWeight <= 0f)
			{
				return this.animatedPosition;
			}
			Vector3 a = this.bone.position;
			Vector3 point = a - this.planeBone1.position;
			planeRotationOffset = this.GetPlaneRotation(solver) * Quaternion.Inverse(this.animatedPlaneRotation);
			a = solver.GetNode(this.plane1ChainIndex, this.plane1NodeIndex).solverPosition + planeRotationOffset * point;
			planeRotationOffset = Quaternion.Lerp(Quaternion.identity, planeRotationOffset, this.maintainRelativePositionWeight);
			return Vector3.Lerp(this.animatedPosition, a + solver.GetNode(this.chainIndex, this.nodeIndex).offset, this.maintainRelativePositionWeight);
		}

		// Token: 0x0400017F RID: 383
		public Transform bone;

		// Token: 0x04000180 RID: 384
		public Transform target;

		// Token: 0x04000181 RID: 385
		[Range(0f, 1f)]
		public float positionWeight;

		// Token: 0x04000182 RID: 386
		[Range(0f, 1f)]
		public float rotationWeight;

		// Token: 0x04000183 RID: 387
		public Vector3 position = Vector3.zero;

		// Token: 0x04000184 RID: 388
		public Quaternion rotation = Quaternion.identity;

		// Token: 0x04000185 RID: 389
		public Vector3 positionOffset;

		// Token: 0x04000186 RID: 390
		public bool effectChildNodes = true;

		// Token: 0x04000187 RID: 391
		[Range(0f, 1f)]
		public float maintainRelativePositionWeight;

		// Token: 0x04000188 RID: 392
		public Transform[] childBones = new Transform[0];

		// Token: 0x04000189 RID: 393
		public Transform planeBone1;

		// Token: 0x0400018A RID: 394
		public Transform planeBone2;

		// Token: 0x0400018B RID: 395
		public Transform planeBone3;

		// Token: 0x0400018C RID: 396
		public Quaternion planeRotationOffset = Quaternion.identity;

		// Token: 0x0400018D RID: 397
		public float posW;

		// Token: 0x0400018E RID: 398
		public float rotW;

		// Token: 0x0400018F RID: 399
		public Vector3[] localPositions = new Vector3[0];

		// Token: 0x04000190 RID: 400
		public bool usePlaneNodes;

		// Token: 0x04000191 RID: 401
		public Quaternion animatedPlaneRotation = Quaternion.identity;

		// Token: 0x04000192 RID: 402
		public Vector3 animatedPosition;

		// Token: 0x04000193 RID: 403
		public bool firstUpdate;

		// Token: 0x04000194 RID: 404
		public int chainIndex = -1;

		// Token: 0x04000195 RID: 405
		public int nodeIndex = -1;

		// Token: 0x04000196 RID: 406
		public int plane1ChainIndex;

		// Token: 0x04000197 RID: 407
		public int plane1NodeIndex = -1;

		// Token: 0x04000198 RID: 408
		public int plane2ChainIndex = -1;

		// Token: 0x04000199 RID: 409
		public int plane2NodeIndex = -1;

		// Token: 0x0400019A RID: 410
		public int plane3ChainIndex = -1;

		// Token: 0x0400019B RID: 411
		public int plane3NodeIndex = -1;

		// Token: 0x0400019C RID: 412
		public int[] childChainIndexes = new int[0];

		// Token: 0x0400019D RID: 413
		public int[] childNodeIndexes = new int[0];
	}
}
